01A isolates experiments
if (run_scripts) source("script/01A-isolates_experiments-01-metadata.R")
Isolate IDs
68 isolates were used in the pairwise competition assay. The csv
contains:
ExpID: isolation ID used by Djordje. The first and
second numbers indicate inoculum and replicates in Goldford2018.
ID: Sanger sequencing ID. Unique ID for sequenced
isolates from Sanchez lab.
Community: community ID used in the competition
assay.
Isolate: Isolates ID within a community ID, used in the
competition assay.
isolates_ID_match <- read_csv("~/Dropbox/lab/emergent-coexistence/data/temp/isolates_ID_match.csv", col_types = cols())
isolates_ID_match
01B isolates sanger sequencing
- Read and align isolate 16S sequences. 1) Read raw
.ab1
file and 2) Merge F and R sequences.
- Classify isolate taxonomy using RDP classifier.
rRDP
- Align seqeunces using MUSCLE.
msa
- Build phylogenetic tree by using FastTree or RAxML.
ggtree
Read isolate 16S sequences
Read and merge ab1 files
This script reads the raw ab1 file from Sanger sequences and merges
the forward and backward sequences. It may take ~20 minutes to read all
420 sequences from 210 isolates.
#' This script takes ~10mins to run
#' Do not run this script if `isolates_16S` is already available.
if (run_scripts) source("script/01B-isolate_sanger_seq-01-read_align.R")
These isolates include Djordje’s isolates from simplicity paper, and
Jean’s isolates from random environments. - ID: Sanger
sequencing ID. - Sequence: Sanger sequence. -
ConsensusLength:
isolates_16S <- read_csv("~/Dropbox/lab/emergent-coexistence/data/temp/isolates_16S.csv", col_types = cols())
isolates_16S
Taxonomy classifier
Use RDP taxonomy classifier to determine the isolates’ taxonomy.
Assign fermenter/respirator and gram positive/negative according to
families.
# This may take a few seconds
if (run_scripts) source("script/01B-isolate_sanger_seq-02-RDP.R")
ID
Fermenter: Fermenting sugar or not accroding to the
taxanomy
GramPositive: gram positive or negative.
Family
Genus
GenusScore
Sequence
Multiple sequence alignment and make tree
Save the multiple sequence alignment result, ggtree-compatible tree,
and the isolate RDP information with the tree in
data/temp/isolates_sanger_seq.Rdata.
aln
aln2
tree
isolates_seq
if (run_scripts) source("script/01B-isolate_sanger_seq-03-make_tree.R")
load("~/Dropbox/lab/emergent-coexistence/data/temp/isolates_sanger_seq.Rdata")
isolates_seq
DNAStringSet object of length 68:
width seq names
[1] 657 TACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGCAAGCC...TTAATTCGATGCAACGCGAAGAACCTTACCTACTCTTGACATCC 1.2.A.1
[2] 826 TACGGGAGGCAGCAGTGGGGAATATTGGACAATGGGCGAAAGCC...TTACCAGCACGTTATGGTGGGCACTCTAAGGAGACTGCCGGTGA 1.4.A.1
[3] 525 GACGTTACCCGCAGAAGAAGCACCGGCTAACTCCGTGCCAGCAG...CGATGCAACGCGAAGAACCTTACCTACTCTTGACATCCAGAGAA 1.4.A.3
[4] 790 TACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGCAAGCC...GTTAAGTCCCGCAACGAGCGCAACCCTTATCCTTTGTTGCCAGC 1.4.B.4
[5] 741 TCACCAAGGCGACGATCCGTAACTGGTCTGAGAGGATGATCAGT...AGCAACGCGAAGAACCTTACCAGGCCTTGACATGCAGAGAACTT 1.6.A.1
... ... ...
[64] 716 TCCCTAGCTGGTCTGAGAGGATGACCAGCCACACTGGAACTGAG...TTTAATTCGATGCAACGCGAAGAACCTTACCTACTCTTGACATC 11.2.B.8.2
[65] 838 TGAGAGGATGACCAGCCACACTGGAACTGAGACACGGTCCAGAC...TTAAGTCCCGCAACGAGCGCAACCCTTATCCTTTGTTGCCAGCG 11.1.C.1
[66] 676 TACGGGAGGCAGCAGTGGGGAATATTGGACAATGGGCGAAAGCC...AGAACCTTACCAGGCCTTGACATGCAGAGAACTTTCCAGAGATG 11.5.B.2
[67] 772 NNNNNNNNNNNNNNNNNNNNNTGCAANTCGAGCGGCAGCGGGAA...NGCGAAAGCGTGGGGAGCAAACAGGATTAGATACCCTGGGTANN 2.6.A.5
[68] 803 NNNNNNGNNNNNNNNNNGCAGTCGAGCGGTAGCACAGGGAGCTT...GTCCACGCCGTAAACGATGTCGACTTGGNNNTTGTGCCCNTGNN 10.2.C.4
Plot basic tree

01C isolates OD and CFU conversion
- Read ODs of isolates and pairs that were measured in pairwise
competition experiment.
isolates_OD.csv
- Read isolates’ CFU on monoculture
isolates_CFU_T8.csv
- Match isolates’ OD and CFU
isolates_OD_CFU.csv
- Calculate uncertainty in epsilon using error propagation theory
Read OD (isolates and pairs)
Read the OD data generated from the analysis script for each
experiment batch. The table below is the communities in each
experimental batch.
| B2 |
C11R1 (except for isolate 1), C10R2, C2R6, C2R8, C7R1, C8R4 |
| C |
C11R1 isolate 1 (the OD data is in OD_C2.csv) |
| C2 |
C11R2 |
| D2 |
C11R5, C1R2, C1R4, C1R6, C1R7, C4R1 |
Read the OD files and export an overall OD data in csv
output/OD.csv and an isolate OD csv
output/isolates_OD.csv
if (run_scripts) source("script/01C-isolates_OD_CFU-01-read_OD.R")
Isolate OD at each transfer. Abs values have been averaged out among
replicates.
There are 68 isolates used in the pairwise competition
experiments.
Write all OD data in data/temp/OD.csv and isolate OD in
data/temp/isolates_OD.csv
isolates_OD <- read_csv("~/Dropbox/lab/emergent-coexistence/data/temp/isolates_OD.csv", col_types = cols())
isolates_OD
Read isolates CFU
if (run_scripts) source("script/01C-isolates_OD_CFU-02-read_CFU.R")
Colony counts at the given dilution factors.
There are 68 isolates used in the pairwise competition
experiments.
Write isolate OD and CFU in
data/temp/isolates_OD_CFU.csv
Epsilon: OD-CFU conversion coefficient
if (run_scripts) source("script/01C-isolates_OD_CFU-03-epsilon.R")
To determine the outcomes of pairwise competition, I compare the
frequencies changes between T1 and T8, which were empirically measured
at different approaches and have to be converted into the same unit for
comparison.
T1 frequencies are determined by mixing two isolate inocula with
the standardized OD (OD620 = 0.1) at three initial frequencies: 5:95,
50:50, 95:5. T1 frequencies are thus OD frequencies.
T8 frequencies are determined by plating the mature media (48
hour growth cycle) on rich agar plates and counting the colony of each
isolate. T8 frequencies are thus CFU frequencies.
In this section, I convert the OD frequencies at T1 to CFU
frequencies. For each isolate, the CFU and OD have the following
relationships.
\[CFU_A = \frac{OD_A DF_A
v_A}{\epsilon_A}\]
\[CFU_A = \epsilon_A OD_A DF_A
v_A\]
where \(OD\) is the measured OD at
620 nm, \(DF\) is the dilution factor
(\(10^4\) or \(10^5\)), \(v\) is the plating volume (20 uL for all
experiment) \(\epsilon\) is the
conversion coefficient between OD and CFU.
isolates_epsilon <- read_csv("~/Dropbox/lab/emergent-coexistence/data/temp/isolates_epsilon.csv", col_types = cols())
isolates_epsilon
01D isolates growth rates
if (run_scripts) source("script/01D-isolates_growth_rate-01-read_data.R")
isolates_growth_traits <- read_csv("~/Dropbox/lab/emergent-coexistence/data/temp/isolates_growth_traits.csv", col_type = cols())
isolates_growth_traits
isolates_growth_traits contains many columns. CS is a
wildcard for any carbon source measured. - r_CS_*hr: growth
rates on carbon sources at 12, 16, 28, 48 hr, measured from the growth
curve data. Data from Sylvie
data/raw/growth_rate/raw_gcurves_all_sylvies.csv. -
X_CS_*hr: secreted acids (acetate, lactate, succinate)
amount at 0, 16, 28, 48 hr. Data from Sylvie
data/raw/growth_rate/Estrela_2021_isolates_ph_OAs.csv -
pH_*hr: pH measured at 0, 16, 28, 48 hr. Data from Sylvie
data/raw/growth_rate/Estrela_2021_isolates_ph_OAs.csv. -
PreferredCS and SecretedCS: acid preference
determined by the sequence of acid used, manually corrected by
eyeballing the figure 01D-byproduct_conc.png. Data from
Sylvie
data/raw/growth_rate/Estrela_2021_isolates_ph_OAs.csv. -
ByproductSum_*hr: sum of acids produced at 0, 16, 28, 48
hr. Data from Sylvie
data/raw/growth_rate/raw_gcurves_all_sylvies.
Summary
Plot isolates’ functions (Thies section is deprecated)
Growth rates on varied CSs
isolates %>%
select(ID, Fermenter, starts_with("r_")) %>%
pivot_longer(cols = c(-Fermenter, -ID), names_prefix = "r_", names_to = "CS", values_to = "r") %>%
mutate(CS = factor(CS, c("glucose", "acetate", "lactate", "succinate", "gluconate", "ketogluconate"))) %>%
filter(!is.na(Fermenter)) %>%
ggplot() +
geom_histogram(aes(x = r, fill = Fermenter), color = 1, binwidth = 0.005) +
facet_wrap(.~CS, nrow = 3, scales = "free_y") +
theme_classic()
Warning: Removed 846 rows containing non-finite values (stat_bin).

OD at 16hr on varied CSs
isolates %>%
select(ID, Fermenter, starts_with("OD")) %>%
pivot_longer(cols = c(-Fermenter, -ID), names_prefix = "OD620_16h_", names_to = "CS", values_to = "r") %>%
mutate(CS = factor(CS, c("glucose", "acetate", "succinate", "citrate", "fructose", "arabinose", "galactose", "ribose", "glycerol", "pyruvate", "malate", "fumarate"))) %>%
filter(!is.na(Fermenter)) %>%
ggplot() +
geom_histogram(aes(x = r, fill = Fermenter), color = 1, binwidth = 0.01) +
facet_wrap(.~CS, nrow = 4, scales = "free_y") +
theme_classic()
Warning: Removed 720 rows containing non-finite values (stat_bin).

Acids production
isolates %>%
select(ID, Fermenter, starts_with("X_"), starts_with("pH")) %>%
pivot_longer(cols = c(-Fermenter, -ID), names_prefix = "X_", names_sep = "_", names_to = c("CS", "Time"), values_to = "Amount") %>%
mutate(Time = sub("hr", "", Time)) %>%
mutate(CS = factor(CS, c("pH", "acetate", "lactate", "succinate"))) %>%
filter(!is.na(Fermenter)) %>%
ggplot() +
geom_line(aes(x = Time, y = Amount, group = ID, color = Fermenter)) +
facet_wrap(.~CS, nrow = 2, scales = "free_y") +
theme_classic()
Warning: Removed 180 row(s) containing missing values (geom_path).

LS0tCnRpdGxlOiAiQW5hbHlzaXMgb24gaXNvbGF0ZXMgdXNlZCBpbiBwYWlyd2lzZSBjb21wZXRpdGlvbnMiCmF1dGhvcjogIkNoYW5nLVl1IENoYW5nIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOiAgCiAgICB0b2M6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRn0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNhY2hlID0gRkFMU0UsIGVjaG8gPSBUUlVFKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKcnVuX3NjcmlwdHMgPC0gRgpgYGAKCgojIDAxQSBpc29sYXRlcyBleHBlcmltZW50cwoKYGBge3J9CmlmIChydW5fc2NyaXB0cykgc291cmNlKCJzY3JpcHQvMDFBLWlzb2xhdGVzX2V4cGVyaW1lbnRzLTAxLW1ldGFkYXRhLlIiKQpgYGAKCgojIyBJc29sYXRlIElEcwoKNjggaXNvbGF0ZXMgd2VyZSB1c2VkIGluIHRoZSBwYWlyd2lzZSBjb21wZXRpdGlvbiBhc3NheS4gVGhlIGNzdiBjb250YWluczoKCi0gYEV4cElEYDogaXNvbGF0aW9uIElEIHVzZWQgYnkgRGpvcmRqZS4gVGhlIGZpcnN0IGFuZCBzZWNvbmQgbnVtYmVycyBpbmRpY2F0ZSBpbm9jdWx1bSBhbmQgcmVwbGljYXRlcyBpbiBHb2xkZm9yZDIwMTguCi0gYElEYDogU2FuZ2VyIHNlcXVlbmNpbmcgSUQuIFVuaXF1ZSBJRCBmb3Igc2VxdWVuY2VkIGlzb2xhdGVzIGZyb20gU2FuY2hleiBsYWIuCi0gYENvbW11bml0eWA6IGNvbW11bml0eSBJRCB1c2VkIGluIHRoZSBjb21wZXRpdGlvbiBhc3NheS4KLSBgSXNvbGF0ZWA6IElzb2xhdGVzIElEIHdpdGhpbiBhIGNvbW11bml0eSBJRCwgdXNlZCBpbiB0aGUgY29tcGV0aXRpb24gYXNzYXkuCgoKYGBge3J9Cmlzb2xhdGVzX0lEX21hdGNoIDwtIHJlYWRfY3N2KCJ+L0Ryb3Bib3gvbGFiL2VtZXJnZW50LWNvZXhpc3RlbmNlL2RhdGEvdGVtcC9pc29sYXRlc19JRF9tYXRjaC5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKCkpCmlzb2xhdGVzX0lEX21hdGNoCmBgYAoKIyMgQ29tbXVuaXR5IG1ldGFkYXRhCgpDb21tdW5pdHkgSURzIGFuZCBiYXNpYyBpbmZvcm1hdGlvbgoKMTMgc2VsZi1hc3NlbWJsZWQgY29tbXVuaXRpZXMsIHR3byBhY3Jvc3MtY29tbXVuaXR5IGFzc2VtYmx5LCB0d28gcmFuZG9tIGFzc21lYmx5CgpgYGB7cn0KY29tbXVuaXRpZXMgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS9vdXRwdXQvY29tbXVuaXRpZXMuY3N2IiwgY29sX3R5cGVzID0gY29scygpKQpjb21tdW5pdGllcwpgYGAKCiMgMDFCIGlzb2xhdGVzIHNhbmdlciBzZXF1ZW5jaW5nCgotICAgUmVhZCBhbmQgYWxpZ24gaXNvbGF0ZSAxNlMgc2VxdWVuY2VzLiAxKSBSZWFkIHJhdyBgLmFiMWAgZmlsZSBhbmQgMikgTWVyZ2UgRiBhbmQgUiBzZXF1ZW5jZXMuCi0gICBDbGFzc2lmeSBpc29sYXRlIHRheG9ub215IHVzaW5nIFJEUCBjbGFzc2lmaWVyLiBgclJEUGAKLSAgIEFsaWduIHNlcWV1bmNlcyB1c2luZyBNVVNDTEUuIGBtc2FgCi0gICBCdWlsZCBwaHlsb2dlbmV0aWMgdHJlZSBieSB1c2luZyBGYXN0VHJlZSBvciBSQXhNTC4gYGdndHJlZWAKCiMjIFJlYWQgaXNvbGF0ZSAxNlMgc2VxdWVuY2VzCgpSZWFkIGFuZCBtZXJnZSBhYjEgZmlsZXMKClRoaXMgc2NyaXB0IHJlYWRzIHRoZSByYXcgYWIxIGZpbGUgZnJvbSBTYW5nZXIgc2VxdWVuY2VzIGFuZCBtZXJnZXMgdGhlIGZvcndhcmQgYW5kIGJhY2t3YXJkIHNlcXVlbmNlcy4gSXQgbWF5IHRha2UgXH4yMCBtaW51dGVzIHRvIHJlYWQgYWxsIDQyMCBzZXF1ZW5jZXMgZnJvbSAyMTAgaXNvbGF0ZXMuCgpgYGB7cn0KIycgVGhpcyBzY3JpcHQgdGFrZXMgfjEwbWlucyB0byBydW4KIycgRG8gbm90IHJ1biB0aGlzIHNjcmlwdCBpZiBgaXNvbGF0ZXNfMTZTYCBpcyBhbHJlYWR5IGF2YWlsYWJsZS4gCmlmIChydW5fc2NyaXB0cykgc291cmNlKCJzY3JpcHQvMDFCLWlzb2xhdGVfc2FuZ2VyX3NlcS0wMS1yZWFkX2FsaWduLlIiKQpgYGAKClRoZXNlIGlzb2xhdGVzIGluY2x1ZGUgRGpvcmRqZSdzIGlzb2xhdGVzIGZyb20gc2ltcGxpY2l0eSBwYXBlciwgYW5kIEplYW4ncyBpc29sYXRlcyBmcm9tIHJhbmRvbSBlbnZpcm9ubWVudHMuCi0gYElEYDogU2FuZ2VyIHNlcXVlbmNpbmcgSUQuCi0gYFNlcXVlbmNlYDogU2FuZ2VyIHNlcXVlbmNlLgotIGBDb25zZW5zdXNMZW5ndGhgOiAKCmBgYHtyfQppc29sYXRlc18xNlMgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2lzb2xhdGVzXzE2Uy5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKCkpCmlzb2xhdGVzXzE2UwpgYGAKCiMjIFRheG9ub215IGNsYXNzaWZpZXIKClVzZSBSRFAgdGF4b25vbXkgY2xhc3NpZmllciB0byBkZXRlcm1pbmUgdGhlIGlzb2xhdGVzJyB0YXhvbm9teS4gQXNzaWduIGZlcm1lbnRlci9yZXNwaXJhdG9yIGFuZCBncmFtIHBvc2l0aXZlL25lZ2F0aXZlIGFjY29yZGluZyB0byBmYW1pbGllcy4gCgpgYGB7cn0KIyBUaGlzIG1heSB0YWtlIGEgZmV3IHNlY29uZHMKaWYgKHJ1bl9zY3JpcHRzKSBzb3VyY2UoInNjcmlwdC8wMUItaXNvbGF0ZV9zYW5nZXJfc2VxLTAyLVJEUC5SIikKYGBgCgotIGBJRGAKLSBgRmVybWVudGVyYDogRmVybWVudGluZyBzdWdhciBvciBub3QgYWNjcm9kaW5nIHRvIHRoZSB0YXhhbm9teQotIGBHcmFtUG9zaXRpdmVgOiBncmFtIHBvc2l0aXZlIG9yIG5lZ2F0aXZlLgotIGBGYW1pbHlgCi0gYEdlbnVzYAotIGBHZW51c1Njb3JlYAotIGBTZXF1ZW5jZWAKCmBgYHtyfQppc29sYXRlc19SRFAgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2lzb2xhdGVzX1JEUC5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKCkpCmlzb2xhdGVzX1JEUApgYGAKCiMjIE11bHRpcGxlIHNlcXVlbmNlIGFsaWdubWVudCBhbmQgbWFrZSB0cmVlCgpTYXZlIHRoZSBtdWx0aXBsZSBzZXF1ZW5jZSBhbGlnbm1lbnQgcmVzdWx0LCBnZ3RyZWUtY29tcGF0aWJsZSB0cmVlLCBhbmQgdGhlIGlzb2xhdGUgUkRQIGluZm9ybWF0aW9uIHdpdGggdGhlIHRyZWUgaW4gYGRhdGEvdGVtcC9pc29sYXRlc19zYW5nZXJfc2VxLlJkYXRhYC4KCi0gYGFsbmAKLSBgYWxuMmAKLSBgdHJlZWAKLSBgaXNvbGF0ZXNfc2VxYAoKYGBge3J9CmlmIChydW5fc2NyaXB0cykgc291cmNlKCJzY3JpcHQvMDFCLWlzb2xhdGVfc2FuZ2VyX3NlcS0wMy1tYWtlX3RyZWUuUiIpCmBgYAoKYGBge3J9CmxvYWQoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2lzb2xhdGVzX3Nhbmdlcl9zZXEuUmRhdGEiKQppc29sYXRlc19zZXEKYGBgCgoKUGxvdCBiYXNpYyB0cmVlCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTB9CmdndHJlZSh0cmVlKSArIGdncGxvdDI6OnhsaW0oMCwgMC41KQpgYGAKCgoKIyAwMUMgaXNvbGF0ZXMgT0QgYW5kIENGVSBjb252ZXJzaW9uCgotICAgUmVhZCBPRHMgb2YgaXNvbGF0ZXMgYW5kIHBhaXJzIHRoYXQgd2VyZSBtZWFzdXJlZCBpbiBwYWlyd2lzZSBjb21wZXRpdGlvbiBleHBlcmltZW50LiBgaXNvbGF0ZXNfT0QuY3N2YAotICAgUmVhZCBpc29sYXRlcycgQ0ZVIG9uIG1vbm9jdWx0dXJlIGBpc29sYXRlc19DRlVfVDguY3N2YAotICAgTWF0Y2ggaXNvbGF0ZXMnIE9EIGFuZCBDRlUgYGlzb2xhdGVzX09EX0NGVS5jc3ZgCi0gICBDYWxjdWxhdGUgdW5jZXJ0YWludHkgaW4gZXBzaWxvbiB1c2luZyBlcnJvciBwcm9wYWdhdGlvbiB0aGVvcnkKCiMjIFJlYWQgT0QgKGlzb2xhdGVzIGFuZCBwYWlycykKClJlYWQgdGhlIE9EIGRhdGEgZ2VuZXJhdGVkIGZyb20gdGhlIGFuYWx5c2lzIHNjcmlwdCBmb3IgZWFjaCBleHBlcmltZW50IGJhdGNoLiBUaGUgdGFibGUgYmVsb3cgaXMgdGhlIGNvbW11bml0aWVzIGluIGVhY2ggZXhwZXJpbWVudGFsIGJhdGNoLgoKfCBFeHBlcmltZW50YWwgYmF0Y2ggfCBDb21tdW5pdHkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAp8IEIyICAgICAgICAgICAgICAgICB8IEMxMVIxIChleGNlcHQgZm9yIGlzb2xhdGUgMSksIEMxMFIyLCBDMlI2LCBDMlI4LCBDN1IxLCBDOFI0IHwKfCBDICAgICAgICAgICAgICAgICAgfCBDMTFSMSBpc29sYXRlIDEgKHRoZSBPRCBkYXRhIGlzIGluIGBPRF9DMi5jc3ZgKSAgICAgICAgICAgICB8CnwgQzIgICAgICAgICAgICAgICAgIHwgQzExUjIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8IEQyICAgICAgICAgICAgICAgICB8IEMxMVI1LCBDMVIyLCBDMVI0LCBDMVI2LCBDMVI3LCBDNFIxICAgICAgICAgICAgICAgICAgICAgICAgIHwKClJlYWQgdGhlIE9EIGZpbGVzIGFuZCBleHBvcnQgYW4gb3ZlcmFsbCBPRCBkYXRhIGluIGNzdiBgb3V0cHV0L09ELmNzdmAgYW5kIGFuIGlzb2xhdGUgT0QgY3N2IGBvdXRwdXQvaXNvbGF0ZXNfT0QuY3N2YAoKYGBge3J9CmlmIChydW5fc2NyaXB0cykgc291cmNlKCJzY3JpcHQvMDFDLWlzb2xhdGVzX09EX0NGVS0wMS1yZWFkX09ELlIiKQpgYGAKCklzb2xhdGUgT0QgYXQgZWFjaCB0cmFuc2Zlci4gQWJzIHZhbHVlcyBoYXZlIGJlZW4gYXZlcmFnZWQgb3V0IGFtb25nIHJlcGxpY2F0ZXMuCgpUaGVyZSBhcmUgNjggaXNvbGF0ZXMgdXNlZCBpbiB0aGUgcGFpcndpc2UgY29tcGV0aXRpb24gZXhwZXJpbWVudHMuCgpXcml0ZSBhbGwgT0QgZGF0YSBpbiBgZGF0YS90ZW1wL09ELmNzdmAgYW5kIGlzb2xhdGUgT0QgaW4gYGRhdGEvdGVtcC9pc29sYXRlc19PRC5jc3ZgCgpgYGB7cn0KaXNvbGF0ZXNfT0QgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2lzb2xhdGVzX09ELmNzdiIsIGNvbF90eXBlcyA9IGNvbHMoKSkKaXNvbGF0ZXNfT0QKYGBgCgojIyBSZWFkIGlzb2xhdGVzIENGVQoKYGBge3J9CmlmIChydW5fc2NyaXB0cykgc291cmNlKCJzY3JpcHQvMDFDLWlzb2xhdGVzX09EX0NGVS0wMi1yZWFkX0NGVS5SIikKYGBgCgpDb2xvbnkgY291bnRzIGF0IHRoZSBnaXZlbiBkaWx1dGlvbiBmYWN0b3JzLgoKYGBge3J9Cmlzb2xhdGVzX09EX0NGVSA8LSByZWFkX2Nzdigifi9Ecm9wYm94L2xhYi9lbWVyZ2VudC1jb2V4aXN0ZW5jZS9kYXRhL3RlbXAvaXNvbGF0ZXNfT0RfQ0ZVLmNzdiIsIGNvbF90eXBlID0gY29scygpKQppc29sYXRlc19PRF9DRlUKYGBgCgpUaGVyZSBhcmUgNjggaXNvbGF0ZXMgdXNlZCBpbiB0aGUgcGFpcndpc2UgY29tcGV0aXRpb24gZXhwZXJpbWVudHMuCgpXcml0ZSBpc29sYXRlIE9EIGFuZCBDRlUgaW4gYGRhdGEvdGVtcC9pc29sYXRlc19PRF9DRlUuY3N2YAoKIyMgRXBzaWxvbjogT0QtQ0ZVIGNvbnZlcnNpb24gY29lZmZpY2llbnQKCmBgYHtyIHdhcm5pbmcgPSBGfQppZiAocnVuX3NjcmlwdHMpIHNvdXJjZSgic2NyaXB0LzAxQy1pc29sYXRlc19PRF9DRlUtMDMtZXBzaWxvbi5SIikKYGBgCgpUbyBkZXRlcm1pbmUgdGhlIG91dGNvbWVzIG9mIHBhaXJ3aXNlIGNvbXBldGl0aW9uLCBJIGNvbXBhcmUgdGhlIGZyZXF1ZW5jaWVzIGNoYW5nZXMgYmV0d2VlbiBUMSBhbmQgVDgsIHdoaWNoIHdlcmUgZW1waXJpY2FsbHkgbWVhc3VyZWQgYXQgZGlmZmVyZW50IGFwcHJvYWNoZXMgYW5kIGhhdmUgdG8gYmUgY29udmVydGVkIGludG8gdGhlIHNhbWUgdW5pdCBmb3IgY29tcGFyaXNvbi4KCi0gICBUMSBmcmVxdWVuY2llcyBhcmUgZGV0ZXJtaW5lZCBieSBtaXhpbmcgdHdvIGlzb2xhdGUgaW5vY3VsYSB3aXRoIHRoZSBzdGFuZGFyZGl6ZWQgT0QgKE9ENjIwID0gMC4xKSBhdCB0aHJlZSBpbml0aWFsIGZyZXF1ZW5jaWVzOiA1Ojk1LCA1MDo1MCwgOTU6NS4gVDEgZnJlcXVlbmNpZXMgYXJlIHRodXMgT0QgZnJlcXVlbmNpZXMuCgotICAgVDggZnJlcXVlbmNpZXMgYXJlIGRldGVybWluZWQgYnkgcGxhdGluZyB0aGUgbWF0dXJlIG1lZGlhICg0OCBob3VyIGdyb3d0aCBjeWNsZSkgb24gcmljaCBhZ2FyIHBsYXRlcyBhbmQgY291bnRpbmcgdGhlIGNvbG9ueSBvZiBlYWNoIGlzb2xhdGUuIFQ4IGZyZXF1ZW5jaWVzIGFyZSB0aHVzIENGVSBmcmVxdWVuY2llcy4KCkluIHRoaXMgc2VjdGlvbiwgSSBjb252ZXJ0IHRoZSBPRCBmcmVxdWVuY2llcyBhdCBUMSB0byBDRlUgZnJlcXVlbmNpZXMuIEZvciBlYWNoIGlzb2xhdGUsIHRoZSBDRlUgYW5kIE9EIGhhdmUgdGhlIGZvbGxvd2luZyByZWxhdGlvbnNoaXBzLgoKJCRDRlVfQSA9IFxmcmFje09EX0EgREZfQSB2X0F9e1xlcHNpbG9uX0F9JCQKCiQkQ0ZVX0EgPSBcZXBzaWxvbl9BIE9EX0EgREZfQSB2X0EkJAoKd2hlcmUgJE9EJCBpcyB0aGUgbWVhc3VyZWQgT0QgYXQgNjIwIG5tLCAkREYkIGlzIHRoZSBkaWx1dGlvbiBmYWN0b3IgKCQxMF40JCBvciAkMTBeNSQpLCAkdiQgaXMgdGhlIHBsYXRpbmcgdm9sdW1lICgyMCB1TCBmb3IgYWxsIGV4cGVyaW1lbnQpICRcZXBzaWxvbiQgaXMgdGhlIGNvbnZlcnNpb24gY29lZmZpY2llbnQgYmV0d2VlbiBPRCBhbmQgQ0ZVLgoKYGBge3J9Cmlzb2xhdGVzX2Vwc2lsb24gPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2lzb2xhdGVzX2Vwc2lsb24uY3N2IiwgY29sX3R5cGVzID0gY29scygpKQppc29sYXRlc19lcHNpbG9uCmBgYAoKIyAwMUQgaXNvbGF0ZXMgZ3Jvd3RoIHJhdGVzCgoKYGBge3J9CmlmIChydW5fc2NyaXB0cykgc291cmNlKCJzY3JpcHQvMDFELWlzb2xhdGVzX2dyb3d0aF9yYXRlLTAxLXJlYWRfZGF0YS5SIikKYGBgCgoKYGBge3J9Cmlzb2xhdGVzX2dyb3d0aF90cmFpdHMgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2lzb2xhdGVzX2dyb3d0aF90cmFpdHMuY3N2IiwgY29sX3R5cGUgPSBjb2xzKCkpCmlzb2xhdGVzX2dyb3d0aF90cmFpdHMKYGBgCgpgaXNvbGF0ZXNfZ3Jvd3RoX3RyYWl0c2AgY29udGFpbnMgbWFueSBjb2x1bW5zLiBDUyBpcyBhIHdpbGRjYXJkIGZvciBhbnkgY2FyYm9uIHNvdXJjZSBtZWFzdXJlZC4KICAgIC0gYHJfQ1NfKmhyYDogZ3Jvd3RoIHJhdGVzIG9uIGNhcmJvbiBzb3VyY2VzIGF0IDEyLCAxNiwgMjgsIDQ4IGhyLCBtZWFzdXJlZCBmcm9tIHRoZSBncm93dGggY3VydmUgZGF0YS4gRGF0YSBmcm9tIFN5bHZpZSBgZGF0YS9yYXcvZ3Jvd3RoX3JhdGUvcmF3X2djdXJ2ZXNfYWxsX3N5bHZpZXMuY3N2YC4KICAgIC0gYFhfQ1NfKmhyYDogc2VjcmV0ZWQgYWNpZHMgKGFjZXRhdGUsIGxhY3RhdGUsIHN1Y2NpbmF0ZSkgYW1vdW50IGF0IDAsIDE2LCAyOCwgNDggaHIuIERhdGEgZnJvbSBTeWx2aWUgYGRhdGEvcmF3L2dyb3d0aF9yYXRlL0VzdHJlbGFfMjAyMV9pc29sYXRlc19waF9PQXMuY3N2YAogICAgLSBgcEhfKmhyYDogcEggbWVhc3VyZWQgYXQgMCwgMTYsIDI4LCA0OCBoci4gRGF0YSBmcm9tIFN5bHZpZSBgZGF0YS9yYXcvZ3Jvd3RoX3JhdGUvRXN0cmVsYV8yMDIxX2lzb2xhdGVzX3BoX09Bcy5jc3ZgLgogICAgLSBgUHJlZmVycmVkQ1NgIGFuZCBgU2VjcmV0ZWRDU2A6IGFjaWQgcHJlZmVyZW5jZSBkZXRlcm1pbmVkIGJ5IHRoZSBzZXF1ZW5jZSBvZiBhY2lkIHVzZWQsIG1hbnVhbGx5IGNvcnJlY3RlZCBieSBleWViYWxsaW5nIHRoZSBmaWd1cmUgYDAxRC1ieXByb2R1Y3RfY29uYy5wbmdgLiBEYXRhIGZyb20gU3lsdmllIGBkYXRhL3Jhdy9ncm93dGhfcmF0ZS9Fc3RyZWxhXzIwMjFfaXNvbGF0ZXNfcGhfT0FzLmNzdmAuCiAgICAtIGBCeXByb2R1Y3RTdW1fKmhyYDogc3VtIG9mIGFjaWRzIHByb2R1Y2VkIGF0IDAsIDE2LCAyOCwgNDggaHIuIERhdGEgZnJvbSBTeWx2aWUgIGBkYXRhL3Jhdy9ncm93dGhfcmF0ZS9yYXdfZ2N1cnZlc19hbGxfc3lsdmllc2AuCgoKCiMgMDFFIG1hdGNoIGlzb2xhdGVzIHRvIEVTViBmb3IgY29tbXVuaXR5IGFidW5kYW51Y2UKCgpSZWFkIGNvbW11bml0eSBFU1Ygc2VxdWVuY2VzCgpgYGB7cn0KaWYgKHJ1bl9zY3JpcHRzKSBzb3VyY2UoInNjcmlwdC8wMUUtbWF0Y2hfY29tbXVuaXR5X2FidW5kYW5jZS0wMS1jb21tdW5pdHlfc2VxdWVuY2UuUiIpCmBgYAoKT1RVIHRhYmxlIG91dHB1dCBgY29tbXVuaXRpZXNfYWJ1bmRhbmNlYCBjb21lcyBmcm9tIHRoZSBjdXJhdGVkIGNvbW11bml0eSBFU1YgdGFibGUgZnJvbSBTeWx2aWUuCgpJIGZvcm1hdHRlZCB0aGUgdGFibGUgc28gdGhhdCBpdCBoYXMgdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6CgotICAgYFNhbXBsZUlEYDogZXhwZXJpbWVudCBJRCB1c2VkIGJ5IE5hbnhpIG9yIFN5bHZpZS4KLSAgIGBDb21tdW5pdHlgOiBjb21tdW5pdHksIGZvciBpbnN0YW5jZSwgQzJSNCBvciBDMVJwb29sLgotICAgYFRyYW5zZmVyYDogdGhlIHRyYW5zZmVyIHdoZW4gdGhlIGNvbW11bml0eSB3YXMgc2VxdWVuY2VkLgotICAgYEFkdW5kYW5jZWA6IHRoZSBudW1iZXIgb2YgdGhpcyBzZXF1ZW5jZSBpbiB0aGUgY29tbXVuaXR5LgotICAgYFJlbGF0aXZlQWJ1bmRhbmNlYAotICAgYENvbW11bml0eUVTVklEYDogdGhlIHNlcXVlbmNlIGlkZW50aWZpZXIuIFRoaXMgaWRlbnRpZmllciBpcyBjb21tdW5pdHktc2VxdWVuY2Ugc3BlY2lmaWMuCi0gICBgRVNWYDogdGhlIEROQSBzZXF1ZW5jZSBpbiAxNnMgVjQgcmVnaW9uLgotICAgYENhcmJvblNvdXJjZWA6IHRoZSBjYXJib24gc291cmNlIHVzZWQgZm9yIGFzc2VtYmx5Ci0gICBgT3JkZXJgLCBgRmFtaWx5YCwgYW5kIGBHZW51c2A6IFNJTFZBIGFzc2lnbmVkIHRheG9ub215CgoKYGBge3IgZWNobyA9IFR9CmNvbW11bml0aWVzX2FidW5kYW5jZSA8LSByZWFkX2Nzdigifi9Ecm9wYm94L2xhYi9lbWVyZ2VudC1jb2V4aXN0ZW5jZS9kYXRhL3RlbXAvY29tbXVuaXRpZXNfYWJ1bmRhbmNlLmNzdiIsIGNvbF90eXBlcyA9IGNvbHMoKSkKY29tbXVuaXRpZXNfYWJ1bmRhbmNlCmBgYAoKCiMjIE1hdGNoIGNvbW11bml0eSBFU1ZzIGFuZCBpc29sYXRlIFNhbmdlciBzZXF1ZW5jZXMKCmBgYHtyfQojIEl0IG1heSB0YWtlIDEwIG1pbnMKaWYgKHJ1bl9zY3JpcHRzKSBzb3VyY2UoInNjcmlwdC8wMUUtbWF0Y2hfY29tbXVuaXR5X2FidW5kYW5jZS0wMi1tYXRjaF9pc29sYXRlXzE2Uy5SIikKYGBgCgpJVVBBQyBub3RhdGlvbiBmb3IgRE5BIGJhc2UgcGFpcnMKClcsIFMsIE0sIEssIFIsIFkgcmVwcmVzZW50IHR3byBwb3NzaWJpbGl0aWVzIGZvciBvbmUgYmFzZSBwYWlyIEIsIEQsIEgsIFYgcmVwcmVzZW50IHRocmVlIHBvc3NpYmxpdGllcyBOIG1lYW5zIGFueSBudWNsZW90aWRlcyAoYnV0IG5vdCBhIGdhcCkKCkkgdGVzdGVkIGZpdmUgYWxpZ25tZW50IG1ldGhvZHMgaW4gYEJpb3N0cmluZ3M6OnBhaXJ3aXNlQWxpZ25tZW50KClgCgpgYGB7ciBlY2hvID0gVH0Kc2VxdWVuY2VzX2FsaWdubWVudCA8LSByZWFkX2Nzdigifi9Ecm9wYm94L2xhYi9lbWVyZ2VudC1jb2V4aXN0ZW5jZS9kYXRhL3RlbXAvc2VxdWVuY2VzX2FsaWdubWVudC5jc3YiLCBjb2xfdHlwZSA9IGNvbHMoKSkKc2VxdWVuY2VzX2FsaWdubWVudApgYGAKCgojIyBSZWxhdGl2ZSBhYnVuZGFuY2UgZXhwbGFpbmVkIGJ5IHRoZSBzZXF1ZW5jZXMKCmBgYHtyIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0KaWYgKHJ1bl9zY3JpcHRzKSBzb3VyY2UoInNjcmlwdC8wMUUtbWF0Y2hfY29tbXVuaXR5X2FidW5kYW5jZS0wMy1tYXRjaGVkX2FidW5kYW5jZS5SIikKYGBgCgpFU1YgYWJ1bmRhbmNlcyBvZiAxMyBjb21tdW5pdGllcyB1c2VkIGluIHRoZSBjb21wZXRpdGlvbiBhc3NheQoKYGBge3IgZmlnLndpZHRoID0gNSwgZmlnLmhlaWdodCA9IDN9CnBsb3RfYWJ1bmRhbmNlIDwtIGZ1bmN0aW9uKGRmLCBsYWJlbF94ID0gIkNvbW11bml0eSIsIGxhYmVsX3kgPSAiUmVsYXRpdmVBYnVuZGFuY2UiLCBmaWxsID0gIkNvbW11bml0eUVTVklEIikgewogICAgZ2dwbG90KGRmKSArCiAgICAgICAgZ2VvbV9iYXIoYWVzX3N0cmluZyh4ID0gbGFiZWxfeCwgeSA9IGxhYmVsX3ksIGZpbGwgPSBmaWxsKSwKICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQgPSAiaWRlbnRpdHkiLCBjb2wgPSAxKSArCiAgICAgICAgdGhlbWVfYncoKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkKfQpjb21tdW5pdGllc19hYnVuZGFuY2UgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2NvbW11bml0aWVzX2FidW5kYW5jZS5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKCkpCmNvbW11bml0aWVzX2FidW5kYW5jZSAlPiUgcGxvdF9hYnVuZGFuY2UobGFiZWxfeCA9ICJDb21tdW5pdHkiLCBsYWJlbF95ID0gIlJlbGF0aXZlQWJ1bmRhbmNlIiwgZmlsbCA9ICJFU1ZGYW1pbHkiKQpgYGAKCkFidW5kYW5jZXMgb2YgRVNWcyBtYXRjaGVkIHRvIFNhbmdlcnMKCmBgYHtyfQppc29sYXRlc19hYnVuZGFuY2UgPC0gcmVhZF9jc3YoIn4vRHJvcGJveC9sYWIvZW1lcmdlbnQtY29leGlzdGVuY2UvZGF0YS90ZW1wL2lzb2xhdGVzX2FidW5kYW5jZS5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKCkpCmlzb2xhdGVzX1JEUCA8LSByZWFkX2Nzdigifi9Ecm9wYm94L2xhYi9lbWVyZ2VudC1jb2V4aXN0ZW5jZS9kYXRhL3RlbXAvaXNvbGF0ZXNfUkRQLmNzdiIsIGNvbF90eXBlcyA9IGNvbHMoKSkKIyBDb2xvciBzZXRzIGZyb20gU3lsdmllCmNvbG9yX3NldHMgPC0gdGliYmxlKENvbG9yID0gYygieWVsbG93IiwgImRlZXBza3libHVlMyIsICJibHVlIiwgImRhcmtvcmNoaWQyIiwgImZpcmVicmljayIsICJvcmFuZ2UyIiwgImdyZXkiKSwKICBGYW1pbHkgPSBjKCJBZXJvbW9uYWRhY2VhZSIsICJFbnRlcm9iYWN0ZXJpYWNlYWUiLCAiTW9yYXhlbGxhY2VhZSIsICJQc2V1ZG9tb25hZGFjZWFlIiwiQ29tYW1vbmFkYWNlYWUiLCJBbGNhbGlnZW5hY2VhZSIsICJTcGhpbmdvYmFjdGVyaWFjZWFlIikpCgppc29sYXRlc19hYnVuZGFuY2UgJT4lCiAgICBsZWZ0X2pvaW4oaXNvbGF0ZXNfUkRQKSAlPiUKICAgIG11dGF0ZShDb21tdW5pdHkgPSBvcmRlcmVkKENvbW11bml0eSwgIGNvbW11bml0aWVzJENvbW11bml0eSkpICU+JQogICAgcGxvdF9hYnVuZGFuY2UobGFiZWxfeCA9ICJDb21tdW5pdHkiLCBsYWJlbF95ID0gIiBSZWxhdGl2ZUFidW5kYW5jZSIsIGZpbGwgPSAiRmFtaWx5IikgKwogICAgbGFicyh4ID0gIiIsIHkgPSAiUmVsYXRpdmUgYWJ1bmRhbmNlIikgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc2V0TmFtZXMoY29sb3Jfc2V0cyRDb2xvciwgY29sb3Jfc2V0cyRGYW1pbHkpKSArCiAgICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZD1jKDAsMCkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9YygwLDApLCBsaW1pdHMgPSBjKDAsMSksIGJyZWFrcyA9IHNlcSgwLDEsIC4yNSkpIAoKYGBgCgoKIyBTdW1tYXJ5CgojIyBDb21iaW5lIGFuZCBnZW5lcmF0ZSB0aGUgaXNvbGF0ZSBtZXRhZGF0YSBmaWxlCgpgYGB7cn0KaWYgKHJ1bl9zY3JpcHRzKSBzb3VyY2UoInNjcmlwdC8wMS1pc29sYXRlcy0wMS1yZWFkX21hdGNoX2lzb2xhdGUuUiIpCmBgYAoKSXNvbGF0ZXMgaW5mb3JtYXRpb24gaW4gb25lIGRhdGEuZnJhbWUgYGlzb2xhdGVzYC4gNjggaXNvbGF0ZXMKCmBgYHtyfQppc29sYXRlcyA8LSByZWFkX2Nzdigifi9Ecm9wYm94L2xhYi9lbWVyZ2VudC1jb2V4aXN0ZW5jZS9kYXRhL291dHB1dC9pc29sYXRlcy5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKCkpCmlzb2xhdGVzCmBgYAoKCgoKCiMjIFBsb3QgaXNvbGF0ZXMnIGZ1bmN0aW9ucyAoVGhpZXMgc2VjdGlvbiBpcyBkZXByZWNhdGVkKQoKIyMjIEdyb3d0aCByYXRlcyBvbiB2YXJpZWQgQ1NzCgpgYGB7cn0KaXNvbGF0ZXMgJT4lCiAgICBzZWxlY3QoSUQsIEZlcm1lbnRlciwgc3RhcnRzX3dpdGgoInJfIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1GZXJtZW50ZXIsIC1JRCksIG5hbWVzX3ByZWZpeCA9ICJyXyIsIG5hbWVzX3RvID0gIkNTIiwgdmFsdWVzX3RvID0gInIiKSAlPiUKICAgIG11dGF0ZShDUyA9IGZhY3RvcihDUywgYygiZ2x1Y29zZSIsICJhY2V0YXRlIiwgImxhY3RhdGUiLCAic3VjY2luYXRlIiwgImdsdWNvbmF0ZSIsICJrZXRvZ2x1Y29uYXRlIikpKSAlPiUKICAgIGZpbHRlcighaXMubmEoRmVybWVudGVyKSkgJT4lCiAgICBnZ3Bsb3QoKSArCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IHIsIGZpbGwgPSBGZXJtZW50ZXIpLCBjb2xvciA9IDEsIGJpbndpZHRoID0gMC4wMDUpICsKICAgIGZhY2V0X3dyYXAoLn5DUywgbnJvdyA9IDMsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgICB0aGVtZV9jbGFzc2ljKCkKYGBgCgojIyMgT0QgYXQgMTZociBvbiB2YXJpZWQgQ1NzCgpgYGB7cn0KaXNvbGF0ZXMgJT4lCiAgICBzZWxlY3QoSUQsIEZlcm1lbnRlciwgc3RhcnRzX3dpdGgoIk9EIikpICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1GZXJtZW50ZXIsIC1JRCksIG5hbWVzX3ByZWZpeCA9ICJPRDYyMF8xNmhfIiwgbmFtZXNfdG8gPSAiQ1MiLCB2YWx1ZXNfdG8gPSAiciIpICU+JQogICAgbXV0YXRlKENTID0gZmFjdG9yKENTLCBjKCJnbHVjb3NlIiwgImFjZXRhdGUiLCAic3VjY2luYXRlIiwgImNpdHJhdGUiLCAiZnJ1Y3Rvc2UiLCAiYXJhYmlub3NlIiwgImdhbGFjdG9zZSIsICJyaWJvc2UiLCAiZ2x5Y2Vyb2wiLCAicHlydXZhdGUiLCAibWFsYXRlIiwgImZ1bWFyYXRlIikpKSAlPiUKICAgIGZpbHRlcighaXMubmEoRmVybWVudGVyKSkgJT4lCiAgICBnZ3Bsb3QoKSArCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IHIsIGZpbGwgPSBGZXJtZW50ZXIpLCBjb2xvciA9IDEsIGJpbndpZHRoID0gMC4wMSkgKwogICAgZmFjZXRfd3JhcCgufkNTLCBucm93ID0gNCwgc2NhbGVzID0gImZyZWVfeSIpICsKICAgIHRoZW1lX2NsYXNzaWMoKQpgYGAKCgojIyMgQWNpZHMgcHJvZHVjdGlvbgpgYGB7cn0KaXNvbGF0ZXMgJT4lCiAgICBzZWxlY3QoSUQsIEZlcm1lbnRlciwgc3RhcnRzX3dpdGgoIlhfIiksIHN0YXJ0c193aXRoKCJwSCIpKSAlPiUKICAgIHBpdm90X2xvbmdlcihjb2xzID0gYygtRmVybWVudGVyLCAtSUQpLCBuYW1lc19wcmVmaXggPSAiWF8iLCBuYW1lc19zZXAgPSAiXyIsIG5hbWVzX3RvID0gYygiQ1MiLCAiVGltZSIpLCB2YWx1ZXNfdG8gPSAiQW1vdW50IikgJT4lCiAgICBtdXRhdGUoVGltZSA9IHN1YigiaHIiLCAiIiwgVGltZSkpICU+JQogICAgbXV0YXRlKENTID0gZmFjdG9yKENTLCBjKCJwSCIsICJhY2V0YXRlIiwgImxhY3RhdGUiLCAic3VjY2luYXRlIikpKSAlPiUKICAgIGZpbHRlcighaXMubmEoRmVybWVudGVyKSkgJT4lCiAgICBnZ3Bsb3QoKSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSBUaW1lLCB5ID0gQW1vdW50LCBncm91cCA9IElELCBjb2xvciA9IEZlcm1lbnRlcikpICsKICAgIGZhY2V0X3dyYXAoLn5DUywgbnJvdyA9IDIsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgICB0aGVtZV9jbGFzc2ljKCkKYGBgCgoKCgoKCgoKCgoKCgoKCgo=